﻿//
// XN4SL - Xna Framework for Silverlight.
//
using System;
using System.IO;
using System.Xml;
using System.Windows;
using System.Windows.Media;
using System.Windows.Controls;
using System.Collections.Generic;

namespace Xn4Sl.Framework.Audio
{
    /// <summary>
    /// Provides methods and properties to play sound effects.
    /// </summary>
    internal static class SoundPlayer
    {
        /// <summary>
        /// Maximum number of sounds that can play simultaneously.
        /// </summary>
        private const int slotCount = 16;

        /// <summary>
        /// Container for storing sounds and attach to  the main game canvas.
        /// </summary>
        internal static Canvas Content = new Canvas();

        /// <summary>
        /// Playing selected sound effect.
        /// </summary>
        /// <param name="sound">Sound effect to play.</param>
        internal static void Play(SoundEffect sound)
        {
            MediaElement me = GetSoundSlot();
            
            if (me != null)
            {
                me.Volume = SoundEffect.MasterVolume;
                me.SetSource(ReadMediaFile(sound.Name));
            }
        }

        /// <summary>
        /// Reads a media file from XAP package.
        /// </summary>
        /// <param name="filename">Requested file name.</param>
        /// <returns>Audio stream.</returns>
        private static Stream ReadMediaFile(string filename)
        {
            // TODO: Use ContentManager.
            Stream stream = null;

            //
            // Find an asset in a XAP package.
            //
            try
            {
                XmlXapResolver xmlRes = new XmlXapResolver();
                stream = xmlRes.GetEntity(new Uri(filename, UriKind.Relative), null, null) as Stream;
            }
            catch
            {
                throw new Exception(String.Format("Failed to load: {0}!", filename));
            }

            return stream;
        }

        /// <summary>
        /// Gets or creates media element for playing sounds.
        /// </summary>
        /// <returns></returns>
        private static MediaElement GetSoundSlot()
        {
            foreach (MediaElement item in Content.Children)
            {
                if (item.CurrentState == MediaElementState.Paused ||
                    item.CurrentState == MediaElementState.Stopped)
                {
                    return item;
                }
            }
            if (Content.Children.Count < slotCount)
            {
                MediaElement me = new MediaElement() { Volume = 1 };
                Content.Children.Add(me);
                return me;
            }
            return null;
        }
    }
}
